import { reactive, watch } from "vue";
import * as THREE from "three";
import * as TWEEN from "@tweenjs/tween.js";
import { Octree } from "three/examples/jsm/math/Octree";
import { OctreeHelper } from "three/examples/jsm//helpers/OctreeHelper.js";
import { Player } from "./player";
import Typewriter from "typewriter-effect/dist/core";
import { Time } from "./time";
import { loadGLTF } from "../loader";
import { defaultSetting } from "@/config";

interface pointType {
  position: { x: number; y: number };
  degrees: number;
}

export const libraryState: {
  spriteTarget: any;
  tweenPosition: any;
  showMiniMap: boolean;
  point: pointType;
  isMobile: boolean;
  touchIsLocked: boolean;
  modelIndex: number; ///当前模型编号
  sceneIndex: number; ///当前场景编号
  currentScene: any; //当前场景对象
  fileUrls: any[]; //模型资源列表
} = reactive({
  spriteTarget: undefined,
  tweenPosition: undefined,
  showMiniMap: true,
  point: {
    position: { x: 100, y: 100 },
    degrees: 0,
  },
  isMobile: false,
  touchIsLocked: false,
  modelIndex: 1,
  sceneIndex: 1,
  currentScene: undefined,
  fileUrls: [
    "./model/modular_dungeon.glb",
    "./model/collision-world.glb",
    "./model/world.glb",
  ],
});

export class Library {
  modelObj: any;
  scene: any;
  camera: any;
  controls: any;
  tweenPosition: any;
  tweenRotation: any;
  flag: boolean;
  octree: any;
  player: any;
  raycaster: any;
  textMesh: any;
  dotMesh: any;
  backMesh: any;
  deltaTime: any;
  canvasDom: any;

  constructor(scene: any, camera: any, controls: any) {
    this.scene = scene;
    this.camera = camera;
    this.controls = controls;
    this.canvasDom = document.getElementById("library");

    this.tweenPosition = null;
    this.tweenRotation = null;
    libraryState.isMobile = /Mobile/i.test(navigator.userAgent);

    this.flag = false; //控制来回修改top

    defaultSetting.defaultPosition=new THREE.Vector3(0, 0, 0);
    //加载模型
    this.loadModel(libraryState.fileUrls[0]);
    this.addSpriteTag();
    this.addSpriteTag2();
    //添加事件
    if (libraryState.isMobile) this.addTouchEvent();
    this.addClick();
    this.addMiniMap();
    this.initTime();
    //监听
    this.watchModelIndex();
  }
  start(delta: any) {
    // this.deltaTime = Math.min(0.05, delta); //返回0.05, delta之间最小值
    // 更新方法
    this.tweenPosition && this.tweenPosition.update();
    this.tweenRotation && this.tweenRotation.update();
    // this.player &&  this.player.update(this.deltaTime);
    // 使用自定义计时器
    this.player && this.player.update(this.deltaTime.delta);
    this.deltaTime && this.deltaTime.update();
  }
  initTime() {
    this.deltaTime = new Time();
  }
  loadModel(url) {
    // 加载模型，并渲染到画布上
    loadGLTF(url).then((object: any) => {
      this.modelObj = object.scene;
      // console.log(this.modelObj); // 返回组对象Group
      this.scene.add(this.modelObj);
      // 遍历场景中的所有几何体数据
      this.modelObj.traverse((child: any) => {
        if (child.isMesh) {
          child.castShadow = true;
          child.receiveShadow = true;
        }
      });

      //八叉树
      this.octree = new Octree();
      this.octree.fromGraphNode(this.modelObj); // 通过Octree对象来构建节点
      // OctreeHelper
      // const helper = new OctreeHelper(this.octree);
      // helper.visible = true;
      // this.scene.add(helper);
      //添加玩家
      this.player = new Player(this.scene, this.camera, this.octree);
    });
  }
  clearModelStatus() {
    //移除旧模型
    this.player.clear();

    console.log("旧", this.scene.children);
    this.scene.children.forEach((element) => {
      let retain =
        element instanceof THREE.PerspectiveCamera ||
        element instanceof THREE.HemisphereLight ||
        element instanceof THREE.DirectionalLight;
      // if (!retain){this.scene.remove(element);}
      //TODO:清除不干净
      if (
        // element instanceof THREE.Mesh ||
        element instanceof THREE.Sprite ||
        element instanceof THREE.Group
      ) {
        this.scene.remove(element);
      }
    });
  }
  changeModel(index) {
    switch (index) {
      case 1:
        this.loadModel("./model/modular_dungeon.glb");
        this.addSpriteTag();
        this.addSpriteTag2();
        break;
      case 2:
        this.loadModel("./model/collision-world.glb");
        this.addSpriteTag3();
        break;
      default:
        this.loadModel("./model/modular_dungeon.glb");
        this.addSpriteTag();
        this.addSpriteTag2();
        break;
    }
  }
  watchModelIndex() {
    watch(
      () => libraryState.modelIndex,
      (newValue) => {
        console.log("监听切换模型", newValue);
        this.clearModelStatus();
        this.changeModel(newValue);
        //相机归位
        this.camera.lookAt(0, 1, -1);
        this.camera.position.set(0, 0, 0);
        console.log("新", this.scene.children);
      }
    );
  }
  addClick() {
    if (libraryState.isMobile) {
      document.ontouchstart = (event) => {
        this.addTextMeshClick({
          x: event.touches[0].pageX,
          y: event.touches[0].pageY,
        });
      };
    } else {
      document.onclick = (event) => {
        this.addTextMeshClick({
          x: event.pageX,
          y: event.pageY,
        });
      };
    }
  }
  addMiniMap() {
    const typewriter = new Typewriter(
      document.getElementById("miniMap"),
      {
        loop: false,
        delay: 300,
      }
    );
    typewriter
      .typeString(
        "啊~~~你好啊，进入地牢的人。好久没看见活生生的人了，原谅老朽的话多了不少...<br />"
      )
      .typeString("你能帮我出去看看嘛，外面的那只老鸟转来转去，烦死了。<br />")
      .callFunction(() => {})
      .start();
  }
  addSpriteTag() {
    const textmap = new THREE.TextureLoader().load(
      "https://zeno-wxapp-20231109.oss-cn-beijing.aliyuncs.com/bomo-three/model/point/xiaoyouyi.jpg"
    );
    const materialObj = new THREE.SpriteMaterial({
      map: textmap,
    });
    this.textMesh = new THREE.Sprite(materialObj);
    this.textMesh.position.set(10, 2.2, 0.2);
    this.textMesh.rotateY(-Math.PI / 2); //旋转90度
    this.textMesh.name = "text1";
    this.scene.add(this.textMesh);
  }
  addSpriteTag2() {
    const spriteGeometry = new THREE.BoxGeometry(0.4, 0.4, 0.4);
    const shader = new THREE.ShaderMaterial({
      vertexShader: `
        uniform float rotation;
        uniform vec2 center;
        #include <common>
        #include <uv_pars_vertex>
        #include <fog_pars_vertex>
        #include <logdepthbuf_pars_vertex>
        #include <clipping_planes_pars_vertex>
        varying vec2 vUv;
        void main(){
          #include <uv_vertex>
          vec4 mvPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
          vec2 scale;
          scale.x = length(vec3(modelMatrix[0].x,modelMatrix[0].y,modelMatrix[0].z));
          scale.y = length(vec3(modelMatrix[1].x,modelMatrix[1].y,modelMatrix[1].z));
          #ifndef USE_SIZEATTENUATION
            bool isPerspective = isPerspectiveMatrix(projectionMatrix);
            if(isPerspective) scale *= -mvPosition.z;
          #endif
          vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;
          vec2 rotatedPosition;
            rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
            rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
          mvPosition.xy += rotatedPosition;//计算得到所有点的相机空间坐标
            gl_Position = projectionMatrix * mvPosition; //投影坐标系坐标
          vUv = uv;
        }
      `,
      fragmentShader: `
        uniform float uRadius;
        varying vec2 vUv;
        void main(){
          float r = 1.0;
          if(uRadius < 1.0){
            r = uRadius;
          }
          float strength = step(distance(vUv,vec2(0.5)),0.008*r + 0.022);

          float value = (0.9412) * strength + (0.8314) * strength + (0.5333) * strength;
          vec4 color = vec4(
            (0.9412) * strength,
            (0.8314) * strength,
            (0.5333) * strength,
            step(0.1,value)
          );
          float strength2 = step(distance(vUv,vec2(0.5)),0.03+(0.02*uRadius));
          float value2 = (0.9765) * strength2 + (0.8588) * strength2 + (0.6274) * strength2;
          vec4 color2 = vec4(
            (0.9765) * strength2,
            (0.8588) * strength2,
            (0.6274) * strength2,
            step(0.1,value2)*0.45
          );

          gl_FragColor = color;
          if(value < 0.001){
            gl_FragColor = color2;
          }
        }
      `,
      transparent: true,
      uniforms: {
        rotation: {
          value: 0.0,
        },
        center: {
          value: new THREE.Vector2(0.5, 0.5),
        },
        uLight: {
          value: 0.0,
        },
        uRadius: {
          value: 0.0,
        },
      },
    });
    const spriteMesh = new THREE.Mesh(spriteGeometry, shader);
    spriteMesh.position.set(0, 1.5, -6.5);
    spriteMesh.name = "dot";
    this.scene.add(spriteMesh);
    const textmap = new THREE.TextureLoader().load(
      "https://zeno-wxapp-20231109.oss-cn-beijing.aliyuncs.com/bomo-three/model/point/xiaoyouyi.jpg"
    );
    const spriteMaterial = new THREE.MeshBasicMaterial({
      color: 0xf0d488,
      alphaMap: textmap,
      transparent: true,
      depthTest: false,
    });
    const planeGeometry = new THREE.PlaneGeometry(1, 1);
    this.dotMesh = new THREE.Mesh(planeGeometry, spriteMaterial);
    this.dotMesh.position.set(0, 1.8, -6.5);
    this.dotMesh.name = "text2";
    this.scene.add(this.dotMesh);
  }
  addSpriteTag3() {
    const textmap = new THREE.TextureLoader().load(
      "https://bpic.588ku.com/element_origin_min_pic/01/48/00/0157440da9ae935.jpg"
    );
    const materialObj = new THREE.SpriteMaterial({
      map: textmap,
    });
    this.backMesh = new THREE.Sprite(materialObj);
    this.backMesh.position.set(0, 0, 0);
    this.backMesh.rotateY(-Math.PI / 2); //旋转90度
    this.backMesh.name = "back";
    this.scene.add(this.backMesh);
  }
  addTextMeshClick(obj) {
    this.controls.lock();
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2();
    mouse.x = (obj.x / window.innerWidth) * 2 - 1;
    mouse.y = -(obj.y / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, this.camera);
    console.log(obj, mouse, window.innerWidth);
    if (this.textMesh) {
      const intersects = raycaster.intersectObjects([this.textMesh]);
      if (intersects.length > 0) {
        console.log("点击标签-移动");
        // 处理点击事件
        this.moveCameraToMeshPosition(this.textMesh);
      } else if (!this.controls?.isLocked) {
        this.controls.lock();
      }
    }

    if (this.dotMesh) {
      const intersects2 = raycaster.intersectObjects([this.dotMesh]);
      if (intersects2.length > 0) {
        console.log("点击标签-切换场景2");
        // libraryState.sceneIndex = 2;
        libraryState.modelIndex = 2;
      } else if (!this.controls?.isLocked) {
        this.controls.lock();
      }
    }

    if (this.backMesh) {
      const intersects3 = raycaster.intersectObjects([this.backMesh]);
      if (intersects3.length > 0) {
        console.log("点击标签-切换场景1");
        // libraryState.sceneIndex = 2;
        libraryState.modelIndex = 1;
      } else if (!this.controls?.isLocked) {
        this.controls.lock();
      }
    }
  }
  moveCameraToMeshPosition(mesh) {
    // 获取 mesh 的世界坐标
    const targetPosition = new THREE.Vector3();
    mesh.getWorldPosition(targetPosition);
    // 定义相机移动的目标位置
    const target = new THREE.Vector3(targetPosition.x, 0, targetPosition.z);
    libraryState.spriteTarget = target;
    this.player.update(this.deltaTime);
  }
  addTouchEvent() {
    let touchX;
    let touchY;
    this.canvasDom.ontouchstart = (event) => {
      event.preventDefault();
      touchX = event.touches[0].pageX;
      touchY = event.touches[0].pageY;
    };

    this.canvasDom.ontouchmove = (event) => {
      event.preventDefault();
      if (touchX && touchY) {
        var deltaX = event.touches[0].pageX - touchX;
        var deltaY = event.touches[0].pageY - touchY;
        touchX = event.touches[0].pageX;
        touchY = event.touches[0].pageY;

        // 根据触摸事件的移动量调整相机的角度
        this.camera.rotation.y -= deltaX * 0.003; //左右旋转
        this.camera.rotation.x -= deltaY * 0.003; //俯仰旋转
      }
    };
  }
}
